package bookTrading.buyer;

import java.util.Date;
import java.util.Vector;

import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.Behaviour;
import jade.core.behaviours.TickerBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;

public class BookBuyerAgent extends Agent {

	private Vector sellerAgents = new Vector();
	private BookBuyerGui myGui;

	protected void setup() {

		System.out.println("Buyer-agnet " + getAID().getName() + " is ready.");
		// Object[] args = getArguments();
		// if (args != null && args.length > 0) {
		// for (int i = 0; i > args.length; ++i) {
		// AID seller = new AID((String) args[i], AID.ISLOCALNAME);
		// sellerAgents.addElement(seller);
		//
		// }
		// }
		myGui = new BookBuyerGuiImpl();
		myGui.setAgent(this);
		myGui.show();

		addBehaviour(new TickerBehaviour(this, 30000) {

			protected void onTick() {
				System.out.println("����       buyer TickerBehaviour ");
				DFAgentDescription template = new DFAgentDescription();
				ServiceDescription sd = new ServiceDescription();
				sd.setType("book-selling");
				template.addServices(sd);
				try {
					DFAgentDescription[] result = DFService.search(myAgent, template);
					sellerAgents.clear();
					for (int i = 0; i < result.length; ++i) {
						sellerAgents.addElement(result[i].getName());
					}

				} catch (FIPAException fe) {
					fe.printStackTrace();
				}
			}
		});
	}

	protected void takeDown() {

		if (myGui != null) {
			myGui.dispose();
		}
		System.out.println("Buyer-agent" + getAID().getName() + "is terminated.");

	}

	private class PurchaseManager extends TickerBehaviour {

		private String title;
		private int maxPrice;
		private long deadline, initTime, deltaT;

		private PurchaseManager(Agent a, String t, int mp, Date d) {

			super(a, 60000);
			title = t;
			maxPrice = mp;
			deadline = d.getTime();
			initTime = System.currentTimeMillis();/** ��ȡʱ��� */
			deltaT = deadline - initTime;
		}

		protected void onTick() {
			long currentTime = System.currentTimeMillis();
			if (currentTime > deadline) {
				myGui.notifyUser("Cannot buy book: " + title);
				stop();

			} else {
				long elapsedTime = deadline - currentTime;
				int acceptablePrice = (int) Math.round(1.0 * maxPrice * (1.0 * elapsedTime / deltaT));
				// int acceptablePrice = maxPrice;
				/**
				 * ����ѧϰ�����Ϸ�ԭ����ע�ͣ���Ӵ��д�� �
				 */
				myAgent.addBehaviour(new BookNegotiator(title, acceptablePrice, this));
			}

		}
	}

	private class BookNegotiator extends Behaviour {

		private String title;
		private int maxPrice;
		private PurchaseManager manager;
		private AID bestSeller;
		private int bestPrice = 0;
		private int repliesCnt = 0;
		private MessageTemplate mt;
		int step = 0;

		public BookNegotiator(String t, int p, PurchaseManager m) {
			super(null);
			title = t;
			maxPrice = p;
			manager = m;

		}

		public void action() {

			switch (step) {
			case 0:
				ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
				for (int i = 0; i < sellerAgents.size(); ++i) {
					cfp.addReceiver((AID) sellerAgents
							.elementAt(i));/** elementAt(i)����ָ������������� */

				}
				cfp.setContent(title);
				cfp.setConversationId("book-trade");
				cfp.setReplyWith("cfp" + System.currentTimeMillis());
				myAgent.send(cfp);
				mt = MessageTemplate.and(MessageTemplate.MatchConversationId("book-trade"),
						MessageTemplate.MatchInReplyTo(cfp.getReplyWith()));
				step = 1;
				break;

			case 1:
				ACLMessage reply = myAgent.receive(mt);
				if (reply != null) {
					if (reply.getPerformative() == ACLMessage.PROPOSE) {
						int price = Integer.parseInt(reply.getContent());
						myGui.notifyUser(
								"Received Proposal at " + price + " when maximum acceptable price was " + maxPrice);
						if (bestSeller == null || price < bestPrice) {
							bestPrice = price;
							bestSeller = reply.getSender();
						}
					}
					repliesCnt++;
					if (repliesCnt >= sellerAgents.size()) {
						step = 2;
					}
				} else {
					block();
				}
				break;

			case 2:
				if (bestSeller != null && bestPrice <= maxPrice) {
					ACLMessage order = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
					System.out.println("����case2.PROPOSE" + order);
					order.addReceiver(bestSeller);
					order.setContent(title);
					order.setConversationId("book-trade");
					order.setReplyWith("order" + System.currentTimeMillis());
					myAgent.send(order);
					mt = MessageTemplate.and(MessageTemplate.MatchConversationId("book-trade"),
							MessageTemplate.MatchInReplyTo(order.getReplyWith()));
					step = 3;

				} else {
					step = 4;
				}
				break;
			case 3:
				reply = myAgent.receive(mt);
				if (reply != null) {
					if (reply.getPerformative() == ACLMessage.INFORM) {
						System.out.println("����case3.PROPOSE");
						myGui.purchasedBook(title);
						myGui.notifyUser("Book: " + title + " successfully purchased. Price = " + bestPrice);
						manager.stop();
					}
					step = 4;

				} else {
					block();
				}
				break;
			}

		}

		public boolean done() {
			return step == 4;
		}
	}

	public void purchase(String title, int maxPrice, Date deadline) {
		System.out.println("����˹���");
		addBehaviour(new PurchaseManager(this, title, maxPrice, deadline));

	}

	public void setCreditCard(String cc) {

	}

}
